﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team - cellcloudproject@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellPlatformInformation_h
#define CellPlatformInformation_h

#include "CellPrerequisites.h"

namespace cell
{
//
// TODO: 将以下宏移动到 CellPlatform.h ?
//

/* 初始 CPU 配置。
*/
#define CELL_CPU_UNKNOWN    0
#define CELL_CPU_X86        1
#define CELL_CPU_PPC        2
#define CELL_CPU_ARM        3

/* 判断 CPU 类型
*/
#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || \
    (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
#   define CELL_CPU CELL_CPU_X86

#elif CELL_PLATFORM == CELL_PLATFORM_APPLE && defined(__BIG_ENDIAN__)
#   define CELL_CPU CELL_CPU_PPC
#elif CELL_PLATFORM == CELL_PLATFORM_APPLE
#	define CELL_CPU CELL_CPU_X86
#elif CELL_PLATFORM == CELL_PLATFORM_IOS && (defined(__i386__) || defined(__x86_64__))
#	define CELL_CPU CELL_CPU_X86
#elif defined(__arm__)
#	define CELL_CPU CELL_CPU_ARM
#else
#   define CELL_CPU CELL_CPU_UNKNOWN
#endif

/* 判断如何声明变量的对齐。
*/
#if CELL_COMPILER == CELL_COMPILER_MSVC
#   define CELL_ALIGNED_DECL(type, var, alignment)  __declspec(align(alignment)) type var

#elif CELL_COMPILER == CELL_COMPILER_GNUC
#   define CELL_ALIGNED_DECL(type, var, alignment)  type var __attribute__((__aligned__(alignment)))

#else
#   define CELL_ALIGNED_DECL(type, var, alignment)  type var
#endif

/* 判断 SIMD alignment
*/
#if CELL_CPU == CELL_CPU_X86
#   define CELL_SIMD_ALIGNMENT  16

#else
#   define CELL_SIMD_ALIGNMENT  16
#endif

/* 声明变量 SIMD alignment 对齐。
*/
#define CELL_SIMD_ALIGNED_DECL(type, var)   CELL_ALIGNED_DECL(type, var, CELL_SIMD_ALIGNMENT)

/* 定义是否支持 SSE 。
*/
#if CELL_CPU == CELL_CPU_X86 && CELL_COMPILER == CELL_COMPILER_MSVC
#   define __CELL_HAVE_SSE  1
#elif CELL_CPU == CELL_CPU_X86 && CELL_COMPILER == CELL_COMPILER_GNUC
#   define __CELL_HAVE_SSE  1
#endif

/* 定义是否支持 VFP 。
*/
#if CELL_CPU == CELL_CPU_ARM && CELL_COMPILER == CELL_COMPILER_GNUC && defined(__ARM_ARCH_6K__) && defined(__VFP_FP__)
#   define __CELL_HAVE_VFP  1
#endif

/* 定义是否支持 NEON
*/
#if CELL_CPU == CELL_CPU_ARM && CELL_COMPILER == CELL_COMPILER_GNUC && defined(__ARM_ARCH_7A__) && defined(__ARM_NEON__)
#   define __CELL_HAVE_NEON  1
#endif

#ifndef __CELL_HAVE_SSE
#   define __CELL_HAVE_SSE  0
#endif

#ifndef __CELL_HAVE_VFP
#   define __CELL_HAVE_VFP  0
#endif

#ifndef __CELL_HAVE_NEON
#   define __CELL_HAVE_NEON  0
#endif
    
/** \addtogroup Core
 *  @{
 */
/** \addtogroup General
 *  @{
 */

/** 获取运行时平台信息的类。
@remarks
	Cell Cloud 被设计为平台无关的系统，但是系统运行时可能需要平台相关信息。
@note
	该类仅提供给高级用户使用。
*/
class _CellExport PlatformInformation
{
public:

	/// 枚举 CPU 特性。
    enum CpuFeatures
    {
#if CELL_CPU == CELL_CPU_X86
        CPU_FEATURE_SSE         = 1 << 0,
        CPU_FEATURE_SSE2        = 1 << 1,
        CPU_FEATURE_SSE3        = 1 << 2,
        CPU_FEATURE_MMX         = 1 << 3,
        CPU_FEATURE_MMXEXT      = 1 << 4,
        CPU_FEATURE_3DNOW       = 1 << 5,
        CPU_FEATURE_3DNOWEXT    = 1 << 6,
        CPU_FEATURE_CMOV        = 1 << 7,
        CPU_FEATURE_TSC         = 1 << 8,
        CPU_FEATURE_FPU         = 1 << 9,
        CPU_FEATURE_PRO         = 1 << 10,
        CPU_FEATURE_HTT         = 1 << 11,
#elif CELL_CPU == CELL_CPU_ARM
        CPU_FEATURE_VFP         = 1 << 12,
        CPU_FEATURE_NEON        = 1 << 13,
#endif

        CPU_FEATURE_NONE        = 0
    };

	/** 返回 CPU 标识（Identifier）。
	@note
		实际运行时，只在第一次执行该函数时获取 CPU 信息，
		之后调用该函数都是返回已经缓存的数据。
	*/
    static const String& getCpuIdentifier(void);

	/** 返回当前 CPU 支持的已经“或”标记（or-masked）的 CPU 特性枚举值。
	@note
		实际运行时，只在第一次执行该函数时获取 CPU 信息，
		之后调用该函数都是返回已经缓存的数据。
	*/
    static uint getCpuFeatures(void);

	/** 检查当前 CPU 是否具备指定的特性。
	@note
		实际运行时，只在第一次执行该函数时获取 CPU 信息，
		之后调用该函数都是返回已经缓存的数据。
	*/
	static bool hasCpuFeature(CpuFeatures feature);

	/** 将 CPU 信息写入日志。
		*/
	static void log(Logger* pLog);
};

/** @} */
/** @} */
} // end namespace cell

#endif // CellPlatformInformation_h
